﻿using System;
using System.Runtime.Remoting.Messaging;
using System.Web;

namespace OperationPlugins
{
    public static class ContextStorage
    {
        public static void Set<T>(T value) where T : class, new()
        {
            if (value == null)
            {
                throw new ArgumentNullException("value");
            }

            var key = GetKey(typeof(T));
            SetData(key, value);
        }

        public static T Get<T>() where T : class, new()
        {
            var key = GetKey(typeof(T));
            var value = GetData(key) as T;

            if (value == null)
            {
                value = new T();
                SetData(key, value);
            }

            return value;
        }

        private static string GetKey(Type type)
        {
            return string.Format("ContextStorage_{0}", type.FullName);
        }

        /// <summary>
        /// Checks if the HttpContext is available.
        /// </summary>
        private static bool IsHttpContext
        {
            get
            {
                return HttpContext.Current != null;
            }
        }

        /// <summary>
        /// Sets an object into the context.
        /// </summary>
        /// <param name="key">key</param>
        /// <param name="data">data</param>
        private static void SetData(string key, object data)
        {
            if (IsHttpContext)
            {
                HttpContext.Current.Items[key] = data;
            }
            else
            {
                CallContext.SetData(key, data);
            }
        }

        /// <summary>
        /// Gets an object from the context.
        /// </summary>
        /// <param name="key">key</param>
        /// <returns>object or null if not found</returns>
        private static object GetData(string key)
        {
            object data;

            if (IsHttpContext)
            {
                data = HttpContext.Current.Items[key];
            }
            else
            {
                data = CallContext.GetData(key);
            }

            return data;
        }

    }
}
